package se.webbzon.boltzmann.game.object.portal;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;

import javax.media.j3d.Transform3D;
import javax.vecmath.AxisAngle4d;
import javax.vecmath.Vector3d;

import se.webbzon.boltzmann.resource.Resources;
import se.webbzon.oschi01.worldobject.appearance.Appearance3D;
import se.webbzon.oschi01.worldobject.appearance.GroupAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.SimpleAppearance3D;
import se.webbzon.oschi01.worldobject.appearance.YZPlaneAppearance3D;

public class DoubleDoor extends AbstractDoor {
	
	// The maximal angle of the door when it is open
	private static final double maxAngle = 0.75 * Math.PI;
	
	// Whatever this door is an indoor
	private final boolean indoor;
	
	// The hinges of this door
	private final Appearance3D leftHinge, rightHinge;
	
	/*============================================================
	Constructor
	============================================================*/
	
	/** Creates a new left door with the given texture set. **/
	public DoubleDoor(boolean indoor, String textureSetName, Color textureBlending) {
		super(new GroupAppearance3D(0,0/*GroupAppearance3D.EXTENDING*/,null));
		this.indoor = indoor;
		
		GroupAppearance3D appearance = (GroupAppearance3D) getAppearance();
		
		final Transform3D transform = new Transform3D();
		final Vector3d translation = new Vector3d();
		final Vector3d scaling = new Vector3d(1,1,0.5);
		final AxisAngle4d rotation = new AxisAngle4d(0,1,0,Math.PI);
		transform.setRotation(rotation);
		
		// Add a background if not indoors
		if (!indoor) {
			SimpleAppearance3D background = new YZPlaneAppearance3D(0,SimpleAppearance3D.LAYERS,false);
			background.setLayer(-1/16.0, 0, 0);
			background.setColor(Color.black);
			translation.set(0.5, 0, 0);
			transform.setTranslation(translation);

			background.setTransform(transform);
			appearance.addAppearance(background);
		}
		
		// Add hinge groups
		List<Appearance3D> leftAppearances = new ArrayList<Appearance3D>();
		List<Appearance3D> rightAppearances = new ArrayList<Appearance3D>();
		
		final int renderingOrder = indoor ? 1 : 0;
		
		// Create front doors
		{
			transform.setScale(scaling);
			SimpleAppearance3D leftDoorFront = new YZPlaneAppearance3D(renderingOrder,	
												SimpleAppearance3D.LAYERS + 
												SimpleAppearance3D.TEXTURE_REPEATING +
												SimpleAppearance3D.TRANSPARENCY,false);
			SimpleAppearance3D rightDoorFront = new YZPlaneAppearance3D(renderingOrder,
												SimpleAppearance3D.LAYERS + 
												SimpleAppearance3D.TRANSPARENCY,false);
			leftDoorFront.setTextureSet(Resources.getTextureSet(textureSetName));
			leftDoorFront.setColor(textureBlending);
			leftDoorFront.setLayer(-3/16.0, 0, 0);
			leftDoorFront.setHRep(-1);
			rightDoorFront.setTextureSet(Resources.getTextureSet(textureSetName));
			rightDoorFront.setColor(textureBlending);
			rightDoorFront.setLayer(-3/16.0, 0, 0);
			translation.set(0, 0, 0.25);
			transform.setTranslation(translation);
			leftDoorFront.setTransform(transform);
			leftAppearances.add(leftDoorFront);
			translation.set(0, 0, -0.25);
			transform.setTranslation(translation);
			rightDoorFront.setTransform(transform);
			rightAppearances.add(rightDoorFront);
			if (indoor) {
				leftDoorFront.setTransparency(0.5f);
				rightDoorFront.setTransparency(0.5f);
			}
		}
		
		// Create left back door
		{
			rotation.set(0,1,0,0);
			transform.setRotation(rotation);
			SimpleAppearance3D leftDoorBack = new YZPlaneAppearance3D(renderingOrder,
												SimpleAppearance3D.LAYERS +
												SimpleAppearance3D.TRANSPARENCY,false);
			SimpleAppearance3D rightDoorBack = new YZPlaneAppearance3D(renderingOrder,
												SimpleAppearance3D.LAYERS + 
												SimpleAppearance3D.TEXTURE_REPEATING +
												SimpleAppearance3D.TRANSPARENCY,false);
			leftDoorBack.setTextureSet(Resources.getTextureSet(textureSetName));
			leftDoorBack.setColor(textureBlending);
			leftDoorBack.setLayer(-3/16.0, 0, 0);
			rightDoorBack.setTextureSet(Resources.getTextureSet(textureSetName));
			rightDoorBack.setColor(textureBlending);
			rightDoorBack.setLayer(-3/16.0, 0, 0);
			rightDoorBack.setHRep(-1);
			translation.set(0, 0, 0.25);
			transform.setTranslation(translation);
			leftDoorBack.setTransform(transform);
			leftAppearances.add(leftDoorBack);
			translation.set(0, 0, -0.25);
			transform.setTranslation(translation);
			rightDoorBack.setTransform(transform);
			rightAppearances.add(rightDoorBack);
			if (indoor) {
				leftDoorBack.setTransparency(0.5f);
				rightDoorBack.setTransparency(0.5f);
			}
		}
		
		// Add hinges
		{
			scaling.set(1,1,1);
			transform.setScale(scaling);
			leftHinge = new GroupAppearance3D(0,leftAppearances);
			rightHinge = new GroupAppearance3D(0,rightAppearances);
			translation.set(0.5, 0, -0.5);
			transform.setTranslation(translation);
			leftHinge.setTransform(transform);
			translation.set(0.5, 0, 0.5);
			transform.setTranslation(translation);
			rightHinge.setTransform(transform);
		}
		
		appearance.addAppearance(leftHinge);
		appearance.addAppearance(rightHinge);
	}
	
	/*============================================================
	Public Methods
	============================================================*/

	@Override public void onUpdate(double p) {
		final Transform3D transform = new Transform3D();
		double v = indoor ? p : -p;
		final AxisAngle4d rotation = new AxisAngle4d(0,1,0,v * maxAngle);
		leftHinge.getTransform(transform);
		transform.setRotation(rotation);
		leftHinge.setTransform(transform);
		rotation.set(0,1,0,-v * maxAngle);
		rightHinge.getTransform(transform);
		transform.setRotation(rotation);
		rightHinge.setTransform(transform);
	}
	
}
